//gcc -o m msg.c -lpthread
#include <stdio.h>
#include <errno.h>

#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_MSG_LEN 512
static int php_msg = -1;
static int php_msg1 = -1;

static int running = 1;

static void *php_msg_handler_thread(void *arg);
static int msg_send(int msg_id, int fd, char *data);

struct msg_st {
	long mtype;
	char mtext[MAX_MSG_LEN];
};

void logst(struct msg_st some_data);

int main(int argc,char **argv)
{
	printf("go 1 \n");

	if((php_msg= msgget((key_t)100001,0666|IPC_CREAT)) == -1)
	{
		perror("php_msg create");
		return 0;
	}

	if((php_msg1= msgget((key_t)200001,0666|IPC_CREAT)) == -1)
	{
		perror("php_msg create");
		return 0;
	}

	/////////////////////////////////////////////////////////////////////////////////
	pthread_t php_msg_pthread;

	int rs = pthread_create(&php_msg_pthread, NULL, (void*(*)(void*))php_msg_handler_thread, (void *)NULL);
	if(rs!=0)
	{
		perror("php_msg_pthread create");
		return 0;
	}

	pthread_join(php_msg_pthread, NULL);
	return 0;

}

static void *php_msg_handler_thread(void *arg)
{
	
	printf("go 2 \n");
	int count = 0;
	char *data1="ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
	struct msg_st some_data;

	//some_data = malloc( sizeof(struct msg_st) );
	

	memcpy(some_data.mtext, data1, strlen(data1) + 1);
	some_data.mtext[strlen(data1)] = '\0';
	some_data.mtype= 2;
	
	struct msqid_ds msg_info;
	if (msgctl(php_msg1,IPC_STAT,&msg_info) == -1)
	{
		perror("IPC_STAT");
		exit(0);
	}
	else
	{
		printf("There are %d messages; \nTotal number of bytes residing on the queue %d\nMaximum number of bytes on the queue: %d\n",
			msg_info.msg_qnum,msg_info.msg_cbytes,msg_info.msg_qbytes
		);
	}
	while(1)
	{
		if((msgsnd(php_msg1,(void *) & some_data, strlen(data1), IPC_NOWAIT)) == -1)
    	{
    		printf("=>Sent %d times\n", count);

			if (msgctl(php_msg1,IPC_STAT,&msg_info) == -1)
			{
				perror("IPC_STAT");
				exit(0);
			}
			else
			{
				printf("There are %d messages; \nTotal number of bytes residing on the queue %d\nMaximum number of bytes on the queue: %d\n",
					msg_info.msg_qnum,msg_info.msg_cbytes,msg_info.msg_qbytes
				);
			}
			
        	perror("msgsnd");
			if(msgctl(php_msg1,IPC_RMID,0) == -1)
            {        
                    fprintf(stderr,"msgctl(IPC_RMID) failed \n");   
            }else{
            	printf("removed\n");
            }
			exit(0);
    	}
		count++;
		if(count%1000==0){
			printf("Sent %d times\n", count);
			/*if(msgctl(php_msg1,IPC_RMID,0) == -1)  
			{  
				fprintf(stderr,"msgctl(IPC_RMID) failed \n");  
			}
			exit(0);*/
		}
		usleep(1000);	
	}	
	
	printf("go 3 \n");
	struct msg_st php_data;		
	printf("sizeof(struct msg_st)=%d\n",sizeof(struct msg_st));

	char* data;
	data = malloc(MAX_MSG_LEN);
	char *pre = "You told me:";	
	while(running){
		//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 
		if(msgrcv(php_msg,(void *) &php_data, MAX_MSG_LEN, 0 , 0) == -1)
		{
			perror("msgrcv");
			if(errno==E2BIG)
			{				
				if(msgctl(php_msg,IPC_RMID,0) == -1)  
				{  
					fprintf(stderr,"msgctl(IPC_RMID) failed \n");  
				}   
			}
			else if(errno == EINVAL)
			{
				sleep(1);
			}
		}else{		
			printf("recevier mssage : %s , type= %d\n", php_data.mtext, php_data.mtype);
			memset(data, '\0', MAX_MSG_LEN);
			memcpy(data, pre, strlen(pre));

			memcpy(data+strlen(pre), php_data.mtext, strlen(php_data.mtext));
			msg_send(php_msg1, 2, data);
			
			bzero(php_data.mtext, strlen(php_data.mtext));
		}
		//break;
	}
	free(data);
}


static int msg_send(int msg_id, int fd, char *data)
{
	struct msg_st some_data;

	//some_data = malloc( sizeof(struct msg_st) );

	memcpy(some_data.mtext, data, strlen(data) + 1);
	some_data.mtext[strlen(data)] = '\0';
	some_data.mtype= fd;

	printf("will send %s \n", &some_data.mtext);
	//int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 
	if((msgsnd(msg_id,(void *) & some_data, strlen(data), 0)) == -1)			
	{
		perror("msgsnd");
		return 0;
	}

	return 1;
}

void logst(struct msg_st some_data)
{
	FILE *fp;
	fp = fopen("file.dat", "w+");	
	if (!fp)  
	{  
	   printf("open file error!");	
		return;
	}
	
	fwrite(&some_data, sizeof(struct msg_st), 1, fp);  
	fclose(fp);	

}


